feat: extend function documentation#2408
Conversation
| context.block_number(); | ||
| ``` | ||
|
|
||
| :::info *Why do the available global variables differ per execution environment?* |
| ### Data Visibility | ||
| Data visibility is used to describe whether the data (or state) used in a function is generally accessible (public) or on a need to know basis (private). Functions with public data visibility is executed by the sequencer, and functions with private data visibility are executed by the user. For more information on why this is the case, see [communication](../../../concepts/foundation/communication/public_private_calls.md). | ||
|
|
||
| In the coming sections, we are going to see how these two "types" co-exists and interact. |
There was a problem hiding this comment.
| In the coming sections, we are going to see how these two "types" co-exists and interact. | |
| In the following sections, we are going to see how these two "types" co-exists and interact. |
nit ^
|
|
||
| In this example (taken from an escrow contract), the constructor sets the deployer as an `owner`. | ||
| :::danger | ||
| It is not possible to call public functions from within a constructor. Beware that the compiler will not throw an error if you do, but the execution will fail! |
There was a problem hiding this comment.
| It is not possible to call public functions from within a constructor. Beware that the compiler will not throw an error if you do, but the execution will fail! | |
| It is not possible, at this time, to call public functions from within a constructor. Beware that the compiler will not throw an error if you do, but the execution will fail! |
- add a note on why
- say that this is just temporary and working on a fix?
There was a problem hiding this comment.
It is already mentioned in the small list under the constructor, I just created the danger box for extra eye catching.
There was a problem hiding this comment.
Or, the why is not mentioned in there. But where thinking showing that into the limitations page to not bloat in here?
There was a problem hiding this comment.
To not be redundant here, I suggest adding it to the Limitations page and adding a link here.
| ## Visibility | ||
| ## Oracle functions | ||
|
|
||
| An oracle is something that allow us to get data from the outside world into our contracts. The most widely-known types of oracles in blockchain systems are probably Chainlink price feeds, which allow us to get the price of an asset in USD taking non-blockchain data into account. |
There was a problem hiding this comment.
| An oracle is something that allow us to get data from the outside world into our contracts. The most widely-known types of oracles in blockchain systems are probably Chainlink price feeds, which allow us to get the price of an asset in USD taking non-blockchain data into account. | |
| An oracle is something that allows us to get data from the outside world into our contracts. The most widely-known types of oracles in blockchain systems are probably Chainlink price feeds, which allow us to get the price of an asset in USD taking non-blockchain data into account. |
|
|
||
| You could of course provide them to your function as inputs, but then functions that have different underlying notes would end up with different function signatures and thus selectors. Meaning that integrating with many of this would become a pain in the neck for the developers, see some of the motivation behind [EIP-4626](https://eips.ethereum.org/EIPS/eip-4626) for similar case in EVM. | ||
|
|
||
| If we are instead fetching the notes using an oracle call, we can keep the function signature independent of the underlying notes and thus make it much easier to integrate with! A similar idea, but applied to authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation making integrations a breeze, see [AuthWit](../../wallets/main#authorizing-actions) for more information on this. |
There was a problem hiding this comment.
| If we are instead fetching the notes using an oracle call, we can keep the function signature independent of the underlying notes and thus make it much easier to integrate with! A similar idea, but applied to authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation making integrations a breeze, see [AuthWit](../../wallets/main#authorizing-actions) for more information on this. | |
| If we are instead fetching the notes using an oracle call, we can keep the function signature independent of the underlying notes and thus make it much easier to integrate with! A similar idea, but applied to the authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation making integrations a breeze, see [AuthWit](../../wallets/main#authorizing-actions) for more information on this. |
|
|
||
| If we are instead fetching the notes using an oracle call, we can keep the function signature independent of the underlying notes and thus make it much easier to integrate with! A similar idea, but applied to authentication mechanism is used for the Authentication Witnesses that allow us to have a single function signature for any wallet implementation making integrations a breeze, see [AuthWit](../../wallets/main#authorizing-actions) for more information on this. | ||
|
|
||
| Oracles introduce `non determinism` into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise the circuit will be `under constrained` and potentially insecure! |
There was a problem hiding this comment.
| Oracles introduce `non determinism` into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise the circuit will be `under constrained` and potentially insecure! | |
| Oracles introduce **non-determinism** into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise, the circuit will be **under-constrained** and potentially insecure! |
There was a problem hiding this comment.
maybe use italics/bold instead?
| |-> C::example_call | ||
| ``` | ||
|
|
||
| <!-- TODO(md): better names for these examples--> |
There was a problem hiding this comment.
consider foo bar baz?
|
|
||
| --- | ||
|
|
||
| ## Calling functions from other functions |
There was a problem hiding this comment.
this is great but I wonder if these should be in communication instead? or maybe we can delete that? Since I saw a couple other places that talk about public <> private comms
There was a problem hiding this comment.
Think that is because it is in communication for foundations. Like the concepts themselves, but not how you do any of it in code. There it sits in communication together with l1 l2 stuff
There was a problem hiding this comment.
maybe in communication we should link to here then?
|
|
||
|
|
||
| ### Public -> Private | ||
| Wait, I thought you said we could not do this? Well, you are right, we cannot do this directly. However, we can do this indirectly if we are a little cheeky. |
| ### Function visibility | ||
| This is the kind of visibility you are more used to seeing in Solidity and more "normal" programming languages. It is used to describe whether a function is callable from other contracts, or only from within the same contract. | ||
|
|
||
| By default, all functions are callable from other contracts, similarly to the Solidity `public` visibility. To make them only callable from the contract itself, you can mark them as `internal`. Contrary to solidity, we don't have the `external` nor `private` keywords. `external` as it is implided, and `private` since we don't support inheritance and would also be confusing with multiple types of `private`. |
There was a problem hiding this comment.
| By default, all functions are callable from other contracts, similarly to the Solidity `public` visibility. To make them only callable from the contract itself, you can mark them as `internal`. Contrary to solidity, we don't have the `external` nor `private` keywords. `external` as it is implided, and `private` since we don't support inheritance and would also be confusing with multiple types of `private`. | |
| By default, all functions are callable from other contracts, similarly to the Solidity `public` visibility. To make them only callable from the contract itself, you can mark them as `internal`. Contrary to Solidity, we don't have the `external` nor `private` keywords. Functions are implied to be `external`, and `private` differs since we don't support inheritance and it would also be confusing with multiple types of `private` (e.g. in inheritance as well as meaning "secret"). |
| In the example above the Account Contract has been instructed to call two external functions. In the first function all, to `Foo::example_call` a further nested call is performed to `Bar::nested_call`. Finally the account contract makes one last call to `Baz::example_call`. | ||
|
|
||
| Lets further illustrate what these examples could look like | ||
| <!-- TODO: should these move into the docs examples --> |
There was a problem hiding this comment.
Is this to be done before merging this PR?
There was a problem hiding this comment.
No. The example is just to show the ordering, can stand as is.
| Oracles introduce **non-determinism** into a circuit, and thus are `unconstrained`. It is important that any information that is injected into a circuit through an oracle is later constrained for correctness. Otherwise, the circuit will be **under-constrained** and potentially insecure! | ||
|
|
||
| `Aztec.nr` has a module dedicated to its oracles. If you are interested, you can view them by following the link below: | ||
| #include_code oracles-module /yarn-project/aztec-nr/aztec/src/oracle.nr rust |
There was a problem hiding this comment.
Do you want to include the list here instead of just the top of the file?
There was a problem hiding this comment.
The top of the file is essentially just used as a link here, showing the rest the file don't bring much extra data so it is essentially just a reference.
| ## `unconstrained` functions | ||
|
|
||
| To create a public function you can annotate it with the `#[aztec(public)]` attribute. This will make the [public context](../context.mdx#public-context) available within your current function's execution scope. | ||
| Unconstrained functions are are an underlying part of Noir and has a deeper explanation [here](https://noir-lang.org/language_concepts/unconstrained). But in short, they are functions which are not directly constrained and therefore should be seen as untrusted! That they are untrusted means that, for security, the developer must make sure to constrain them when used! |
There was a problem hiding this comment.
| Unconstrained functions are are an underlying part of Noir and has a deeper explanation [here](https://noir-lang.org/language_concepts/unconstrained). But in short, they are functions which are not directly constrained and therefore should be seen as untrusted! That they are untrusted means that, for security, the developer must make sure to constrain them when used! | |
| Unconstrained functions are an underlying part of Noir - a deeper explanation can be found [here](https://noir-lang.org/language_concepts/unconstrained). But in short, they are functions which are not directly constrained and therefore should be seen as untrusted! That they are untrusted means that, for security, the developer must make sure to constrain them when used! |
| Unconstrained functions are are an underlying part of Noir and has a deeper explanation [here](https://noir-lang.org/language_concepts/unconstrained). But in short, they are functions which are not directly constrained and therefore should be seen as untrusted! That they are untrusted means that, for security, the developer must make sure to constrain them when used! | ||
|
|
||
| #include_code functions-OpenFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust | ||
| Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. |
There was a problem hiding this comment.
| Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. | |
| Beyond using them inside your other functions, they are convenient for providing an interface that reads storage, applies logic and returns values to a UI or test. Below is a snippet from exposing the `balance_of_private` function from a token implementation, which allows a user to easily read their balance, similar to the `balanceOf` function in the ERC20 standard. |
|
|
||
| #include_code functions-UncontrainedFunction /yarn-project/noir-contracts/src/contracts/docs_example_contract/src/main.nr rust | ||
| :::info | ||
| Note, that unconstrained functions can have access to both public and private data when executed on users device. This is possible since it is not actually part of the circuits that is executed in contract execution. |
There was a problem hiding this comment.
| Note, that unconstrained functions can have access to both public and private data when executed on users device. This is possible since it is not actually part of the circuits that is executed in contract execution. | |
| Note, that unconstrained functions can have access to both public and private data when executed on the user's device. This is possible since it is not actually part of the circuits that are executed in contract execution. |
|
|
||
| --- | ||
|
|
||
| ## Calling functions from other functions |
There was a problem hiding this comment.
maybe in communication we should link to here then?
Co-authored-by: josh crites <critesjosh@gmail.com> Co-authored-by: Rahul Kothari <rahul.kothari.201@gmail.com>
Co-authored-by: josh crites <critesjosh@gmail.com>
8b90ddb to
e9dc67f
Compare
Addresses miscellaneous issues in the documentation. Building on top of #2408.
Fixes #1609. Based greatly on @Maddiaa0s branch #2082.
Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.